package com.jy.rhin.application.assembler;

import cn.org.chiss.rhin._2015.base.Integer;
import cn.org.chiss.rhin._2015.base.*;
import cn.org.chiss.rhin._2015.base.document.*;
import cn.org.chiss.rhin._2015.base.object.MainID;
import cn.org.chiss.rhin._2015.base.object.ObjectStatus;
import cn.org.chiss.rhin._2015.base.object.ObjectStatusPrimitive;
import cn.org.chiss.rhin._2015.base.object.RegObject;
import com.jy.framework.base.utils.Converter;
import com.jy.rhin.sdk.constants.DateFormatPatternConstants;
import com.jy.rhin.sdk.dto.document.*;
import org.apache.commons.lang.StringUtils;
import org.springframework.util.CollectionUtils;

import java.lang.String;
import java.util.Date;
import java.util.*;

/**
 * @Description: 文档管理转换
 * @Author: lww
 * @Date: 2022/6/7 9:19
 */
public class DocumentManagementAssembler {

    private DocumentManagementAssembler() {
    }

    public static SubmissionSet dtoConvert(SubmissionSet submissionSet, DocumentSubmissionSetDto dto) {
        submissionSet.setId(setIdValue(submissionSet.getId(), dto.getId()));
        submissionSet.setHomeCommunityId(setUriValue(dto.getHomeCommunityId()));
        submissionSet.setSourceId(setOidValue(dto.getSourceId()));
        submissionSet.setUniqueId(setOidValue(dto.getUniqueId()));
        submissionSet.setSubmissionTime(dateConvertDateTime(dto.getSubmissionTime()));
        List<RegObject> regObjectList = submissionSet.getFolderOrDocumentEntryOrAssociation();
        if (!CollectionUtils.isEmpty(regObjectList)) {
            List<RegObject> regObjectListNew = new ArrayList<>();
            List<DocumentFolderDto> folders = dto.getFolders();
            List<DocumentEntryDto> entries = dto.getEntries();
            List<DocumentAssociationDto> associations = dto.getAssociations();
            int fold = 0;
            int entry = 0;
            int association = 0;
            for (RegObject regObject : regObjectList) {
                if (regObject instanceof Folder) {
                    regObjectListNew.add(buildFolder((Folder) regObject, folders.get(fold)));
                    fold++;
                } else if (regObject instanceof DocumentEntry) {
                    regObjectListNew.add(buildDocumentEntry((DocumentEntry) regObject, entries.get(entry)));
                } else if (regObject instanceof Association) {
                    regObjectListNew.add(buildAssociation((Association) regObject, associations.get(association)));
                }
            }
            submissionSet.setFolderOrDocumentEntryOrAssociation(regObjectListNew);
        }
        return submissionSet;
    }

    private static Association buildAssociation(Association association, DocumentAssociationDto associationDto) {
        association.setId(setIdValue(association.getId(), associationDto.getId()));
        association.setStatusCode(setStatusCodeValue(association.getStatusCode(), associationDto.getStatusCode()));
        association.setTypeCode(setAssociationTypeValue(associationDto.getTypeCode()));
        AssociationObject sourceObject = association.getSourceObject();
        if (Objects.nonNull(sourceObject)) {
            sourceObject.setId(setUriValue(associationDto.getSourceId()));
            sourceObject.setStatus(setAssociationStatusValue(sourceObject.getStatus(), associationDto.getSourceStatus()));
        }
        AssociationObject targetObject = association.getTargetObject();
        if (Objects.nonNull(targetObject)) {
            targetObject.setId(setUriValue(associationDto.getTargetId()));
            targetObject.setStatus(setAssociationStatusValue(targetObject.getStatus(), associationDto.getTargetStatus()));
        }
        return association;
    }

    private static DocumentEntry buildDocumentEntry(DocumentEntry entry, DocumentEntryDto entryDto) {
        entry.setId(setIdValue(entry.getId(), entryDto.getId()));
        entry.setFormatCode(setCodeValue(entryDto.getFormatCode()));
        entry.setPatientId(setPatientIdValue(entry.getPatientId(), entryDto.getPatientDomain()));
        entry.setServiceStartTime(dateConvertDateTime(entryDto.getServiceStartTime()));
        entry.setServiceStopTime(dateConvertDateTime(entryDto.getServiceStopTime()));
        entry.setStatusCode(setStatusCodeValue(entry.getStatusCode(), entryDto.getStatusCode()));
        entry.setSize(setIntegerValue(entryDto.getSize()));
        entry.setHash(setStringValue(entryDto.getHash()));
        entry.setUniqueId(setOidValue(entryDto.getUniqueId()));
        entry.setRepositoryUniqueId(setOidValue(entryDto.getRepositoryUniqueId()));
        entry.setHomeCommunityId(setOidValue(entryDto.getHomeCommunityId()));
        entry.setLanguageCode(setCodeValue(entryDto.getLanguageCode()));
        entry.setMimeType(setStringValue(entryDto.getMimeType()));
        return entry;
    }

    private static Folder buildFolder(Folder folder, DocumentFolderDto folderDto) {
        folder.setId(setIdValue(folder.getId(), folderDto.getId()));
        folder.setHomeCommunityId(setOidValue(folderDto.getHomeCommunityId()));
        folder.setPatientId(setPatientIdValue(folder.getPatientId(), folderDto.getPatientDomain()));
        folder.setStatusCode(setStatusCodeValue(folder.getStatusCode(), folderDto.getStatusCode()));
        folder.setUniqueId(setOidValue(folderDto.getUniqueId()));
        folder.setLastUpdateTime(dateConvertDateTime(folderDto.getLastUpdateTime()));
        return folder;
    }

    private static ObjectStatus setStatusCodeValue(ObjectStatus objectStatus, String statusCode) {
        if (Objects.nonNull(objectStatus) && Objects.nonNull(objectStatus.getValue()) && !StringUtils.isEmpty(statusCode)) {
            ObjectStatusPrimitive objectStatusPrimitive = ObjectStatusPrimitive.fromXmlEnumValue(statusCode);
            objectStatus.setValue(objectStatusPrimitive);
            return objectStatus;
        }
        return null;
    }

    private static URI setUriValue(String uri) {
        return StringUtils.isEmpty(uri) ? null : new URI().setValue(uri);
    }

    private static OID setOidValue(String oid) {
        return StringUtils.isEmpty(oid) ? null : new OID().setValue(oid);
    }

    private static cn.org.chiss.rhin._2015.base.String setStringValue(String string) {
        return StringUtils.isEmpty(string) ? null : new cn.org.chiss.rhin._2015.base.String().setValue(string);
    }

    private static Code setCodeValue(String code) {
        return StringUtils.isEmpty(code) ? null : new Code().setValue(code);
    }

    private static Integer setIntegerValue(java.lang.Integer integer) {
        if (Objects.nonNull(integer)) {
            Integer result = new Integer();
            result.setValue(integer);
            return result;
        }
        return null;
    }

    private static MainID setIdValue(MainID mainId, String id) {
        if (Objects.nonNull(mainId) && !StringUtils.isEmpty(id)) {
            mainId.setValue(id);
            return mainId;
        }
        return null;
    }

    private static Identifier setPatientIdValue(Identifier identifier, PatientDomainDto patientDomainDto) {
        if (Objects.isNull(identifier) || Objects.isNull(identifier.getValue()) || Objects.isNull(patientDomainDto)) {
            return null;
        }
        if (!StringUtils.isEmpty(patientDomainDto.getPatientId())) {
            ID id = Optional.ofNullable(identifier.getValue()).orElse(new ID()).setValue(patientDomainDto.getPatientId());
            identifier.setValue(id);
        }
        if (!StringUtils.isEmpty(patientDomainDto.getAppid())) {
            URI system = Optional.ofNullable(identifier.getSystem()).orElse(new URI()).setValue(patientDomainDto.getAppid());
            identifier.setSystem(system);
        }
        return identifier;
    }

    private static AssociationStatus setAssociationStatusValue(AssociationStatus associationStatus, String statusValue) {
        if (Objects.nonNull(associationStatus) && Objects.nonNull(associationStatus.getValue()) && !StringUtils.isEmpty(statusValue)) {
            AssociationStatusPrimitive associationStatusPrimitive = AssociationStatusPrimitive.fromValue(statusValue);
            associationStatus.setValue(associationStatusPrimitive);
            return associationStatus;
        }
        return null;
    }

    private static AssociationType setAssociationTypeValue(String associationType) {
        if (!StringUtils.isEmpty(associationType)) {
            AssociationType type = new AssociationType();
            type.setValue(associationType);
            return type;
        }
        return null;
    }

    private static DateTime dateConvertDateTime(Date date) {
        if (Objects.nonNull(date)) {
            String dateStr = Converter.toString(date, DateFormatPatternConstants.DT19);
            return new DateTime().setValue(dateStr);
        }
        return null;
    }
}
